////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_MATH_MATRIX_3_H__
#define __WN_MATH_MATRIX_3_H__

#include "WNMath/inc/Internal/WNMatrixBase.h"

namespace WNMath {
    template <typename Type> class WNVector2;
    template <typename Type> class WNVector3;
    template <typename Type> class WNMatrix3;

    namespace __WNInternal {
        template <typename Type, typename = WNCore::WNEnableWhen<WN_TRUE>::Value>
        class __WNMatrix3Base : public __WNMatrixBase<WNMatrix3<Type>, Type, 3> {
        protected:
            WN_FORCE_INLINE __WNMatrix3Base() {}
        };

        template <typename Type>
        class __WNMatrix3Base<Type, typename WNCore::WNEnableWhen<WNCore::WNIsReal<Type>::Value>::Value> : public __WNMatrixBase<WNMatrix3<Type>, Type, 3> {
        public:
            WN_FORCE_INLINE WNVector2<Type> TransformVector(const WNVector2<Type>& _vector) const {}
            WN_FORCE_INLINE WNVector3<Type> TransformVector(const WNVector3<Type>& _vector) const {}

            WN_FORCE_INLINE WN_VOID MakeRotation(const Type& _angle);
            WN_FORCE_INLINE WN_VOID MakeOrthogonal() {}

        public:
            static WN_FORCE_INLINE WNMatrix3<Type> CreateRotation(const Type& _angle);
            static WN_FORCE_INLINE WNMatrix3<Type> CreateOrthogonal() {}

        protected:
            WN_FORCE_INLINE __WNMatrix3Base() {}
        };
    }

    template <typename Type>
    class WNMatrix3 : public __WNInternal::__WNMatrix3Base<Type> {
    public:
        WN_FORCE_INLINE WNMatrix3() {}
        WN_FORCE_INLINE WNMatrix3(const WNMatrix3& _matrix);
        explicit WN_FORCE_INLINE WNMatrix3(const Type& _number);
        explicit WN_FORCE_INLINE WNMatrix3(const Type* _numbers);

        WN_FORCE_INLINE WNMatrix3 MakeTranslation(const Type& _translation);
        WN_FORCE_INLINE WNMatrix3 MakeTranslation(const Type& _x, const Type& _y);
        WN_FORCE_INLINE WNMatrix3 MakeScale(const Type& _scale);
        WN_FORCE_INLINE WNMatrix3 MakeScale(const Type& _x, const Type& _y);

    public:
        static WN_FORCE_INLINE WNMatrix3 CreateTranslation(const Type& _translation);
        static WN_FORCE_INLINE WNMatrix3 CreateTranslation(const Type& _x, const Type& _y);
        static WN_FORCE_INLINE WNMatrix3 CreateScale(const Type& _scale);
        static WN_FORCE_INLINE WNMatrix3 CreateScale(const Type& _x, const Type& _y);

    private:
        typedef class __WNInternal::__WNMatrixBase<WNMatrix3<Type>, Type, 3> Base;
    };

    template <typename Type>
    WN_FORCE_INLINE WNMatrix3<Type> operator + (const Type& _number, const WNMatrix3<Type>& _matrix);

    template <typename Type>
    WN_FORCE_INLINE WNMatrix3<Type> operator - (const Type& _number, const WNMatrix3<Type>& _matrix);

    template <typename Type>
    WN_FORCE_INLINE WNMatrix3<Type> operator * (const Type& _number, const WNMatrix3<Type>& _matrix);

    template <typename Type>
    WN_FORCE_INLINE WNMatrix3<Type> operator / (const Type& _number, const WNMatrix3<Type>& _matrix);
}

#include "WNMath/inc/Internal/WNMatrix3.inl"

#endif // __WN_MATH_MATRIX_3_H__